#ifndef __GCODE_H
#define __GCODE_H

#include <stdint.h>
#include <stdbool.h>


#define FAIL(status) {gc.status_code = status; rf_printf("Error:%d", status); return(gc.status_code);}

extern uint32_t startWorkTime;

enum GCSTATUS
{
    GCSTATUS_OK = 0,     // 正常状态
    GCSTATUS_BAD_NUMBER_FORMAT = 1,     // 数字格式错误
    GCSTATUS_EXPECTED_COMMAND_LETTER = 2,     // 不支持的命令字符
    GCSTATUS_UNSUPPORTED_STATEMENT = 3,     // 不支持的命令
    GCSTATUS_FLOATING_POINT_ERROR = 4,     // 浮点数错误
    GCSTATUS_UNSUPPORTED_PARAM = 5,     // 不支持的参数
    GCSTATUS_UNSOPORTED_FEEDRATE = 6,     // 不支持的进料速度
    GCSTATUS_TABLE_SIZE_OVER_X = 7,     // X轴超限
    GCSTATUS_TABLE_SIZE_OVER_Y = 8,     // Y轴超限
    GCSTATUS_TABLE_SIZE_OVER_Z = 9,     // Z轴超限
    GCSTATUS_CANCELED = 101    // 取消指令
};

enum NEXT_ACTION
{
    NEXT_ACTION_DEFAULT = 0,
    NEXT_ACTION_DWELL_G4 = 1,       // 停顿
    NEXT_ACTION_GO_HOME_G28 = 2,
    NEXT_ACTION_RESET_XYZ_G92 = 3,
    NEXT_ACTION_STOP = 4,
    NEXT_ACTION_SEEK_G0 = 5,        // G0 
    NEXT_ACTION_LINEAR_G1 = 6,      // G1
    NEXT_ACTION_EXTRUDER_STOP = 7,
    NEXT_ACTION_EXTRUDER_ON = 8,
    NEXT_ACTION_EXTRUDER_FAST_T = 9,
    NEXT_ACTION_EXTRUDER_WAIT_T = 10,
    NEXT_ACTION_CW_ARC = 11,        //逆圆插补
    NEXT_ACTION_CCW_ARC = 12        //顺园插补
};


#define K_FRQ 10

#ifndef M_PI
#define M_PI 3.141592653589793238462643F
#endif

#define MM_PER_INCH (25.4f)


#define MAX_SPINDEL_TEMPERATURE		48

#define MVECTOR_SZ                  3
#define MAX_SHOW_GCODE_LINES        2   // 最多显示的gcode行数
#define ENABLE_SHOW_MAX_TIME_STEPS  640
#define MAX_STR_SIZE                150

#define CRDS_SIZE   4
#define CRD_X 0
#define CRD_Y 1
#define CRD_Z 2
#define CRD_E 3

#define X_AXIS 0
#define Y_AXIS 1
#define Z_AXIS 2

typedef struct
{
    char cmd[MAX_STR_SIZE];
    int lineNum;
} GCODE_CMD;


#ifndef NO_ACCELERATION_CORRECTION
typedef struct
{
    uint32_t steps[CRDS_SIZE];
    uint32_t frq[CRDS_SIZE];
    uint32_t stepsfrq[CRDS_SIZE];
    uint8_t dir[CRDS_SIZE];
    uint8_t isNullCmd;
    uint8_t changeDir;
    double length;
    int32_t cos_a;
    uint32_t feed_rate;
} MVECTOR;
#endif


typedef struct
{
#ifndef NO_ACCELERATION_CORRECTION
    MVECTOR mvector[MVECTOR_SZ];
    int32_t mvectPtrCur;
    int32_t mvectCnt;
#endif
    GCODE_CMD gcode[MAX_SHOW_GCODE_LINES];
    int gcodePtrCur;
    int32_t stepsFromStartX, stepsFromStartY, stepsFromStartZ, stepsFromStartE;
    int32_t stepsX, stepsY, stepsZ;
} linesBuffer;

extern linesBuffer lbuf;

typedef struct
{
    uint8_t status_code;
    uint8_t inches_mode;                /* 0 = millimeter mode, 1 = inches mode {G20, G21} */
    uint8_t absolute_mode;              /* 0 = relative motion, 1 = absolute motion {G90, G91} */
    uint8_t extruder_absolute_mode;     /* 0 = relative motion, 1 = absolute motion {G90, G91} */
    uint8_t laser_on;                   // 激光打开 {M3, M4}
    uint8_t spindle_on;                 // {M3,M4,M5}
    uint8_t coolant;                    // {M7,M8,M9}
    uint8_t vacuum_on;                  // 吸尘系统开启 {M10, M11}
    uint8_t extruder_on;
    uint8_t plane_select;               // 平面选择  {G17,G18,G19}
    uint8_t spindle_direction;          // 主轴转动方向 0：顺时针 1：逆时针 {M3, M4}
    uint8_t power_on;                   // 电源打开 {M80, M81}
    uint8_t radius_mode;
    uint8_t sop;                        // 打印进度 max:100 min 0
    uint32_t totalfsize;
    uint32_t curfsize;
    double radius;
    double feed_rate, seek_rate;        /* Millimeters/second  {G93,G94}，分开写主要是因为下一次的Gcode在没有输入feed_rate时，保持上一次的值*/
    double extruder_length;
    double extruder_k;
    double position[3];                 /* Where the interpreter considers the tool to be at this point in the code */
    int16_t s_value;                    /* RPM/100 or temperature of the current extruder */
    double e_value;                     /* extruder length*/
    uint8_t next_action;                /* The action that will be taken by the parsed line */
    int pause_value;
    double moveLength;
} parser_state_t;


extern parser_state_t gc;


typedef struct
{
    char letter;
    double value;
    char* line;
    int counter;
} g_cmd_t;

// 200 - full step 360/1.8
#define SM_STEPS_PER_360    (3200 / 2)              //步进电机每一圈要走的步数,根据步进电机芯片配置
#define SM_X_STEPS_PER_360  SM_STEPS_PER_360        //1600 steps/r
#define SM_Y_STEPS_PER_360  SM_STEPS_PER_360        //1600 steps/r
#define SM_Z_STEPS_PER_360  SM_STEPS_PER_360        //1600 steps/r
#define SM_E_STEPS_PER_360  SM_STEPS_PER_360        //1600 steps/r

#define MM_PER_360  5                               //5 r/mm 每一圈走的长度

// 各轴每走一毫米要走的步数 320 step/mm
#define SM_X_STEPS_PER_MM   (SM_X_STEPS_PER_360 / MM_PER_360)       // 320 step/mm 
#define SM_Y_STEPS_PER_MM   (SM_Y_STEPS_PER_360 / MM_PER_360)       // 320 step/mm
#define SM_Z_STEPS_PER_MM   (SM_Z_STEPS_PER_360 / MM_PER_360)       // 320 step/mm
#define SM_E_STEPS_PER_MM   (10)        //how to get it              // 10 step/mm

// 各轴的最大给进速率 mm/min
#define SM_X_MAX_FEEDRATE   2000   // mm/min
#define SM_Y_MAX_FEEDRATE   1600
#define SM_Z_MAX_FEEDRATE   700

// 各轴每秒最大步数 steps/s
#define SM_X_MAX_STEPS_PER_SEC (SM_X_MAX_FEEDRATE * SM_X_STEPS_PER_MM / 60)     //10666.67 steps/s        2000*steps/mm=steps/min
#define SM_Y_MAX_STEPS_PER_SEC (SM_Y_MAX_FEEDRATE * SM_Y_STEPS_PER_MM / 60)     //8533.33  steps/s
#define SM_Z_MAX_STEPS_PER_SEC (SM_Z_MAX_FEEDRATE * SM_Z_STEPS_PER_MM / 60)     //3733.33  steps/s

#define SM_MANUAL_MODE_STEPS_PER_SEC    SM_STEPS_PER_360 * 2 // 640*2 -> 10mm/sec = 600mm/min 手动模式


#define SM_DEFAULT_FEED_RATE 50     // G1
#define SM_DEFAULT_SEEK_RATE 1500   // G0 millimeters per minute

// the speed with which to start from 0, without loss of steps (steps / sec)最大启动速度
#define SM_SMOOTH_START_X   (310 * SM_X_STEPS_PER_MM / 60) // 170 mm/min = 2.3 mm/s          310 * 320steps/mm= mm/min  mm * mm/
#define SM_SMOOTH_START_Y   (180 * SM_Y_STEPS_PER_MM / 60)
#define SM_SMOOTH_START_Z   (120 * SM_Z_STEPS_PER_MM / 60)
//the speed with which you can slow down to 0, without loss of steps (steps / sec)最大减速速度
#define SM_SMOOTH_STOP_X    (320 * SM_X_STEPS_PER_MM / 60) // 170 mm/min = 2.3 mm/s
#define SM_SMOOTH_STOP_Y    (200 * SM_Y_STEPS_PER_MM / 60)
#define SM_SMOOTH_STOP_Z    (140 * SM_Z_STEPS_PER_MM / 60)

//the acceleration in the mm / sec / sec
#define SM_SMOOTH_DFEED_X   75 //60
#define SM_SMOOTH_DFEED_Y   50
#define SM_SMOOTH_DFEED_Z   40 //20

// in the step (msec)
#define SM_SMOOTH_TFEED     (50)

#define SM_SMOOTH_COS_A	        977000
#define SM_TOO_SHORT_SEGMENT_MM 0.015

// for smoth alg.
#define SM_SHORT_SEGMENT_MM         0.5
#define DEFAULT_MM_PER_ARC_SEGMENT  0.2

// Number of arc generation iterations by small angle approximation before exact arc trajectory
// correction. This parameter maybe decreased if there are issues with the accuracy of the arc
// generations. In general, the default value is more than enough for the intended CNC applications
// of grbl, and should be on the order or greater than the size of the buffer to help with the
// computational efficiency of generating arcs.
#define N_ARC_CORRECTION 25 // Integer (1-255)


#define MAX_TABLE_SIZE_X 300
#define MAX_TABLE_SIZE_Y 200
#define MAX_TABLE_SIZE_Z 180

#define GFILE_MODE_MASK_CHK  0
#define GFILE_MODE_MASK_SHOW 2
#define GFILE_MODE_MASK_EXEC 4

void cnc_gfile(char* fileName, int mode);
void gc_init(void);
uint8_t gc_execute_line(const char* line);



void cnc_extruder_stop(void);
void cnc_extruder_on(void);
void cnc_extruder_t(int temperature, int isWait);

#endif


